fix: prevent keypress memory leak with multiple Inquirerer instances#67
Merged
pyramation merged 1 commit intomainfrom Mar 3, 2026
Merged
Conversation
- TerminalKeypress.pause() now resets raw mode (setRawMode(false)) to prevent raw mode from leaking into subsequent text prompts after checkbox/autocomplete - Inquirerer.close() now nullifies this.rl and this.keypress references so subsequent calls detect the closed state and double-close is safe
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes two defensive issues in the
Inquirererlifecycle that contribute to a keypress bug when multiple instances shareprocess.stdin(e.g., duringpgpm init -w).TerminalKeypress.pause()— Now resets raw mode (setRawMode(false)) when pausing. Previously, after acheckbox/autocomplete/listprompt calledpause()on ENTER, raw mode remained enabled, potentially interfering with subsequentreadline-based text prompts.resume()already sets raw mode totrue, so this makes the pair symmetric.destroy()already did this —pause()was the odd one out.Inquirerer.close()— Now nullifiesthis.rlandthis.keypressafter closing/destroying them. This:text(),checkbox(), etc.) detect a closed instance via their existingif (!this.rl)guard and fall back to non-interactive behavior instead of calling methods on a dead readlineCompanion PR: constructive-io/constructive has a separate PR that passes the existing
prompterthrough toinitModule()→scaffoldTemplate()so a secondInquirereris never created onprocess.stdinin the first place.Review & Testing Checklist for Human
pause()raw mode reset doesn't break prompt chaining: After a checkbox prompt, the next text prompt should work correctly.resume()re-enables raw mode, so keypress-based prompts followingpause()should still function. Worth runningpgpm init -winteractively to confirm.prompter.close()twice (orexit()→close()) doesn't throw. Check that prompts afterclose()fall back to non-interactive defaults.pause()/resume()directly onkeypressor check for closed state onInquirerer, verify they still work.Test Plan
inquirererworkflow with multiple checkbox/text question types in sequencepgpm init -wspecifically (once the companion PR lands) to verify no double-echo or input conflictsinquirerertests pass ✅ (they do)Notes
pause()is called by checkbox/autocomplete/list prompts when ENTER is pressed, before resolving the promiseInquirereron stdin) is fixed in the companion PRLink to Devin Session: https://app.devin.ai/sessions/178a5957a56e4141bd3fd4d0a5e4a508
Requested by: @pyramation